package com.easybbs.service.impl;

//import com.easybbs.entity.config.AppConfig;

import com.easybbs.entity.config.AppConfig;
import com.easybbs.entity.constants.Constants;
import com.easybbs.entity.dto.FileUploadDto;
import com.easybbs.entity.dto.SysSetting4AuditDto;
import com.easybbs.entity.enums.*;
import com.easybbs.entity.po.ForumArticle;
import com.easybbs.entity.po.ForumArticleAttachment;
import com.easybbs.entity.po.ForumBoard;
import com.easybbs.entity.po.UserMessage;
import com.easybbs.entity.query.ForumArticleAttachmentQuery;
import com.easybbs.entity.query.ForumArticleQuery;
import com.easybbs.entity.query.SimplePage;
import com.easybbs.entity.vo.PaginationResultVO;
import com.easybbs.exception.BusinessException;
import com.easybbs.mappers.ForumArticleAttachmentMapper;
import com.easybbs.mappers.ForumArticleMapper;
import com.easybbs.service.ForumArticleService;
import com.easybbs.service.ForumBoardService;
import com.easybbs.service.UserInfoService;
import com.easybbs.service.UserMessageService;
import com.easybbs.utils.FileUtils;
import com.easybbs.utils.ImageUtils;
import com.easybbs.utils.StringTools;
import com.easybbs.utils.SysCacheUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.util.Date;
import java.util.List;


/**
 * 文章信息 业务接口实现
 */
@Service("forumArticleService")
public class ForumArticleServiceImpl implements ForumArticleService {

    private static final Logger logger = LoggerFactory.getLogger(ForumArticleServiceImpl.class);

    @Resource
    private ForumArticleMapper<ForumArticle, ForumArticleQuery> forumArticleMapper;

    @Resource
    private ForumArticleAttachmentMapper<ForumArticleAttachment, ForumArticleAttachmentQuery> forumArticleAttachmentMapper;


    @Resource
    private ForumBoardService forumBoardService;

    @Resource
    private UserInfoService userInfoService;


    @Resource
    private UserMessageService userMessageService;

    /**
     * Lazy 延迟渲染
     */
    @Lazy
    @Resource
    private ForumArticleServiceImpl forumArticleService;

    @Autowired
    private FileUtils fileUtils;

    @Autowired
    private ImageUtils imageUtils;

    @Autowired
    private AppConfig appConfig;

    /**
     * 根据条件查询列表
     */
    @Override
    public List<ForumArticle> findListByParam(ForumArticleQuery param) {
        return this.forumArticleMapper.selectList(param);
    }

    /**
     * 根据条件查询列表
     */
    @Override
    public Integer findCountByParam(ForumArticleQuery param) {
        return this.forumArticleMapper.selectCount(param);
    }

    /**
     * 分页查询方法
     */
    @Override
    public PaginationResultVO<ForumArticle> findListByPage(ForumArticleQuery param) {
        int count = this.findCountByParam(param);
        int pageSize = param.getPageSize() == null ? PageSize.SIZE15.getSize() : param.getPageSize();

        SimplePage page = new SimplePage(param.getPageNo(), count, pageSize);
        param.setSimplePage(page);
        List<ForumArticle> list = this.findListByParam(param);
        PaginationResultVO<ForumArticle> result = new PaginationResultVO(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
        return result;
    }

    /**
     * 新增
     */
    @Override
    public Integer add(ForumArticle bean) {
        return this.forumArticleMapper.insert(bean);
    }

    /**
     * 批量新增
     */
    @Override
    public Integer addBatch(List<ForumArticle> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.forumArticleMapper.insertBatch(listBean);
    }

    /**
     * 批量新增或者修改
     */
    @Override
    public Integer addOrUpdateBatch(List<ForumArticle> listBean) {
        if (listBean == null || listBean.isEmpty()) {
            return 0;
        }
        return this.forumArticleMapper.insertOrUpdateBatch(listBean);
    }

    /**
     * 根据ArticleId获取对象
     */
    @Override
    public ForumArticle getForumArticleByArticleId(String articleId) {
        return this.forumArticleMapper.selectByArticleId(articleId);
    }

    /**
     * 根据ArticleId修改
     */
    @Override
    public Integer updateForumArticleByArticleId(ForumArticle bean, String articleId) {
        return this.forumArticleMapper.updateByArticleId(bean, articleId);
    }

    /**
     * 根据ArticleId删除
     */
    @Override
    public Integer deleteForumArticleByArticleId(String articleId) {
        return this.forumArticleMapper.deleteByArticleId(articleId);
    }

    /**
     * 获取文章详情(并且更新文章的浏览量 或者是点赞数量 或者是评论数量）
     *
     * @param artcileId 文章id
     * @return
     */
    @Override
    public ForumArticle readArticle(String artcileId) {
        ForumArticle forumArticle = forumArticleMapper.selectByArticleId(artcileId);
        if (forumArticle == null) {
            throw new BusinessException(ResponseCodeEnum.CODE_404);
        }
        if (ArticleStatusEnum.AUDIT.getStatus().equals(forumArticle.getStatus())) {
            forumArticleMapper.updateArticleCount(UpdateArticleCountTypeEnum.READ_COUNT.getType(), Constants.ONE, artcileId);
        }
        return forumArticle;
    }

    /**
     * 发布文章
     *
     * @param article
     * @param articleAttachment
     * @param cover
     * @param attachment
     * @param isAdmin
     */
    @Override
    public void postArticle(Boolean isAdmin, ForumArticle article, ForumArticleAttachment articleAttachment, MultipartFile cover, MultipartFile attachment) {
        resetBoardInfo(isAdmin, article);

        Date curDate = new Date();
        //生成发布文章的id
        String articleId = StringTools.getRandomString(Constants.LENGTH_15);
        article.setArticleId(articleId);
        article.setPostTime(curDate);
        article.setLastUpdateTime(curDate);

        //上传封面图片了
        if (cover != null) {
            FileUploadDto fileUploadDto = fileUtils.uploadFile2Local(cover, Constants.FILE_FOLDER_IMAGE, FileUploadTypeEnum.ARTICLE_COVER);
            article.setCover(fileUploadDto.getLocalPath());
        }

        //上传附件
        if (attachment != null) {
            //有附件修改
            uploadAttachment(article, articleAttachment, attachment, false);
            article.setAttachmentType(ArticleAttachmentTypeEnum.HAVE_ATTACHMENT.getType());
        } else {
            //没有附件新增
            article.setAttachmentType(ArticleAttachmentTypeEnum.NO_ATTACHMENT.getType());
        }

        //设置文章审核信息
        if (isAdmin) {
            article.setStatus(ArticleStatusEnum.AUDIT.getStatus());
        } else {
            SysSetting4AuditDto auditDto = SysCacheUtils.getSysSetting().getAuditStting();
            article.setStatus(auditDto.getPostAudit() ? ArticleStatusEnum.NO_AUDIT.getStatus() : ArticleStatusEnum.AUDIT.getStatus());
        }

        //替换临时目录图片
        String content = article.getContent();
        if (!StringTools.isEmpty(content)) {
            String month = imageUtils.resetImageHtml(content);
            String replaceMonth = "/" + month + "/";
            content = content.replace(Constants.FILE_FOLEDR_TEMP, replaceMonth);
            article.setContent(content);
            String markdownContent = article.getMarkdownContent();
            //替换markdown图片
            if (!StringTools.isEmpty(markdownContent)) {
                markdownContent = markdownContent.replace(Constants.FILE_FOLEDR_TEMP, replaceMonth);
                article.setMarkdownContent(markdownContent);
            }
        }

        forumArticleMapper.insert(article);

        //增加发帖用户的积分
        Integer postIntegral = SysCacheUtils.getSysSetting().getPostSetting().getPostIntegral();
        if (postIntegral > 0 && ArticleStatusEnum.AUDIT.equals(article.getStatus())) {
            userInfoService.updateUserIntergral(article.getUserId(), UserIntegralOperTypeEnum.POST_ARTICLE, UserIntegralChangeTypeEnum.ADD.getChangeType(), postIntegral);
        }
    }

    /**
     * 更新文章
     *
     * @param isAdmin
     * @param article
     * @param articleAttachment
     * @param cover
     * @param attachment
     */
    @Override
    public void updateArticle(Boolean isAdmin, ForumArticle article, ForumArticleAttachment articleAttachment, MultipartFile cover, MultipartFile attachment) {
        //判断文章是否是本人
        ForumArticle dbInfo = forumArticleMapper.selectByArticleId(article.getArticleId());
        if (!isAdmin && !dbInfo.getUserId().equals(article.getUserId())) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        article.setLastUpdateTime(new Date());
        //重置板块信息
        resetBoardInfo(isAdmin, article);

        //上传封面图片
        if (cover != null) {
            FileUploadDto fileUploadDto = fileUtils.uploadFile2Local(cover, Constants.FILE_FOLDER_IMAGE, FileUploadTypeEnum.ARTICLE_COVER);
            article.setCover(fileUploadDto.getLocalPath());
        }

        //上传附件
        if (attachment != null) {
            //有附件修改
            uploadAttachment(article, articleAttachment, attachment, true);
            article.setAttachmentType(ArticleAttachmentTypeEnum.HAVE_ATTACHMENT.getType());
        }

        ForumArticleAttachment dbAttachment = null;
        ForumArticleAttachmentQuery articleAttachmentQuery = new ForumArticleAttachmentQuery();
        articleAttachmentQuery.setArticleId(article.getArticleId());
        List<ForumArticleAttachment> articleAttachmentList = forumArticleAttachmentMapper.selectList(articleAttachmentQuery);
        if (!articleAttachmentList.isEmpty()) {
            dbAttachment = articleAttachmentList.get(0);
        }

        //判断附件是否存在  修改附件时 我们需要删除文件夹里面的文件 和数据库中的附件数据 之后在替换成更新的数据 所以需要多次判断
        if (dbAttachment != null) {
            if (article.getAttachmentType() == Constants.ZERO) {
                new File(appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + Constants.FILE_FOLDER_ATTACHMENT + dbAttachment.getFilePath()).delete();
                forumArticleAttachmentMapper.deleteByFileId(dbAttachment.getFileId());
            } else {
                //更新积分
                //如果替换了积分 就需要重新添加
                if (!dbAttachment.getIntegral().equals(articleAttachment.getIntegral())) {
                    ForumArticleAttachment integralUpdate = new ForumArticleAttachment();
                    integralUpdate.setIntegral(articleAttachment.getIntegral());
                    forumArticleAttachmentMapper.updateByFileId(integralUpdate, dbAttachment.getFileId());
                }
            }
        }

        //文章是否需要审核
        if (isAdmin) {
            article.setStatus(ArticleStatusEnum.AUDIT.getStatus());
        } else {
            SysSetting4AuditDto auditDto = SysCacheUtils.getSysSetting().getAuditStting();
            article.setStatus(auditDto.getPostAudit() ? ArticleStatusEnum.NO_AUDIT.getStatus() : ArticleStatusEnum.AUDIT.getStatus());
        }

        //替换临时目录图片
        String content = article.getContent();
        if (!StringTools.isEmpty(content)) {
            String month = imageUtils.resetImageHtml(content);
            String replaceMonth = "/" + month + "/";
            content = content.replace(Constants.FILE_FOLEDR_TEMP, replaceMonth);
            article.setContent(content);
            String markdownContent = article.getMarkdownContent();
            //替换markdown图片
            if (!StringTools.isEmpty(markdownContent)) {
                markdownContent = markdownContent.replace(Constants.FILE_FOLEDR_TEMP, replaceMonth);
                article.setMarkdownContent(markdownContent);
            }
        }

        forumArticleMapper.updateByArticleId(article, article.getArticleId());

    }

    /**
     * 重置板块信息
     *
     * @param isAdmin
     * @param forumArticle
     */
    private void resetBoardInfo(Boolean isAdmin, ForumArticle forumArticle) {
        ForumBoard pBoard = forumBoardService.getForumBoardByBoardId(forumArticle.getpBoardId());
        if (pBoard == null || pBoard.getPostType() == Constants.ZERO && !isAdmin) {
            throw new BusinessException("一级板块不存在");
        }
        forumArticle.setpBoardName(pBoard.getBoardName());

        if (forumArticle.getBoardId() != null && forumArticle.getBoardId() != 0) {
            ForumBoard board = forumBoardService.getForumBoardByBoardId(forumArticle.getBoardId());
            if (board == null || board.getPostType() == Constants.ZERO && !isAdmin) {
                throw new BusinessException("二级板块不存在");
            }
            forumArticle.setBoardName(board.getBoardName());
        } else {
            forumArticle.setBoardId(0);
            forumArticle.setBoardName("");
        }
    }

    /**
     * 上传附件的方法修改方法
     * 修改附件也是调用这个
     */
    public void uploadAttachment(ForumArticle article, ForumArticleAttachment articleAttachment, MultipartFile file, Boolean isUpdate) {
        //读取上传附件的最大大小
        Integer allowSizeMb = SysCacheUtils.getSysSetting().getPostSetting().getAttachmentSize(); //通过我们写好的读取缓存的方法来获取
        long allowSize = allowSizeMb * Constants.FILE_SIZE_1M;
        if (file.getSize() > allowSize) {
            throw new BusinessException("附件最大只能上传" + allowSizeMb + "MB");
        }
        //修改文章
        //查询数据库中的附件
        ForumArticleAttachment dbInfo = null;
        if (isUpdate) {
            ForumArticleAttachmentQuery articleAttachmentQuery = new ForumArticleAttachmentQuery();
            articleAttachmentQuery.setArticleId(article.getArticleId());
            List<ForumArticleAttachment> articleAttachmentList = forumArticleAttachmentMapper.selectList(articleAttachmentQuery);
            if (!articleAttachmentList.isEmpty()) {
                //拿到存到的附件
                dbInfo = articleAttachmentList.get(0);
                //删除 文件中的附件
                new File(appConfig.getProjectFolder() + Constants.FILE_FOLDER_FILE + Constants.FILE_FOLDER_ATTACHMENT + dbInfo.getFilePath()).delete();
            }
        }

        //上传文件
        FileUploadDto fileUploadDto = fileUtils.uploadFile2Local(file, Constants.FILE_FOLDER_ATTACHMENT, FileUploadTypeEnum.ARTICLE_ATTACHMENT);

        //数据中没有附件
        if (dbInfo == null) {
            articleAttachment.setFileId(StringTools.getRandomNum(Constants.LENGTH_15));
            articleAttachment.setArticleId(article.getArticleId());
            articleAttachment.setFileName(fileUploadDto.getOriginalFilename());
            articleAttachment.setFilePath(fileUploadDto.getLocalPath());
            articleAttachment.setFileSize(file.getSize());
            articleAttachment.setDownloadCount(Constants.ZERO);
            articleAttachment.setFileType(AttachmentFileTypeEnum.ZIP.getType());
            articleAttachment.setUserId(article.getUserId());
            forumArticleAttachmentMapper.insert(articleAttachment);
        } else {
            //下载的记录还在 只是换了附件
            ForumArticleAttachment updateInfo = new ForumArticleAttachment();
            updateInfo.setFileName(fileUploadDto.getOriginalFilename());
            updateInfo.setFileSize(file.getSize());
            updateInfo.setFilePath(fileUploadDto.getLocalPath());
            forumArticleAttachmentMapper.updateByFileId(updateInfo, dbInfo.getFileId());
        }
    }

    /**
     * 更新模块
     *
     * @param articleId
     * @param pBoardId
     * @param boardId
     */
    @Override
    public void updateBoard(String articleId, Integer pBoardId, Integer boardId) {
        ForumArticle forumArticle = new ForumArticle();
        forumArticle.setpBoardId(pBoardId);
        forumArticle.setBoardId(boardId);

        //刷新板块信息
        resetBoardInfo(true, forumArticle);
        forumArticleMapper.updateByArticleId(forumArticle, articleId);
    }

    /**
     * 删除文章
     *
     * @param articleIds
     */
    @Override
    public void delArticle(String articleIds) {
        //将多个文章id以逗号进行分隔
        String[] articleIdArray = articleIds.split(",");
        //循环每一个articleIdArray中的文章id 进行删除
        for (String articleId : articleIdArray) {
            //这个地方不可以用this调用 会产生依赖循环 需要使用forumArticleService调用 同时需要加上@Lazy注解
            forumArticleService.delArticleSignie(articleId);
        }
    }

    /**
     * 单独的删除方法 不在同一事务中进行删除
     *
     * @param articleId
     */
    @Transactional(rollbackFor = Exception.class)
    public void delArticleSignie(String articleId) {
        //根据文章id获取文章对象信息
        ForumArticle article = getForumArticleByArticleId(articleId);
        if (article == null || ArticleStatusEnum.DEL.getStatus().equals(article.getStatus())) {
            return;
        }
        ForumArticle updateInfo = new ForumArticle();
        updateInfo.setStatus(ArticleStatusEnum.DEL.getStatus());
        forumArticleService.updateForumArticleByArticleId(updateInfo, articleId);

        //闪出文章减去别人获取的积分
        Integer integral = SysCacheUtils.getSysSetting().getPostSetting().getPostIntegral();
        if (integral > 0 && ArticleStatusEnum.AUDIT.getStatus().equals(article.getStatus())) {
            userInfoService.updateUserIntergral(article.getUserId(), UserIntegralOperTypeEnum.DEL_ARTICLE, UserIntegralChangeTypeEnum.REDUCE.getChangeType(), integral);
        }

        //设置删除文章的消息提醒
        UserMessage userMessage = new UserMessage();
        userMessage.setReceivedUserId(article.getUserId());
        userMessage.setMessageType(MessageTypeEnum.SYS.getType());
        userMessage.setCreateTime(new Date());
        userMessage.setStatus(MessageStatusEnum.NO_READ.getStatus());
        userMessage.setMessageContent("您的文章【" + article.getTitle() + "】已被管理员删除");
        userMessageService.add(userMessage);
    }

    /**
     * 审核文章
     *
     * @param articleIds
     */
    @Override
    public void auditArticle(String articleIds) {
        //将多个文章id以逗号进行分隔
        String[] articleIdArray = articleIds.split(",");
        //循环每一个articleIdArray中的文章id 进行删除
        for (String articleId : articleIdArray) {
            //这个地方不可以用this调用 会产生依赖循环 需要使用forumArticleService调用 同时需要加上@Lazy注解
            forumArticleService.auditArticleSignie(articleId);
        }
    }

    /**
     * 审核文章单个方法
     *
     * @param articleId
     */
    @Transactional(rollbackFor = Exception.class)
    public void auditArticleSignie(String articleId) {
        ForumArticle article = getForumArticleByArticleId(articleId);
        if (article == null || !ArticleStatusEnum.NO_AUDIT.getStatus().equals(article.getStatus())) {
            return;
        }
        ForumArticle updateInfo = new ForumArticle();
        updateInfo.setStatus(ArticleStatusEnum.AUDIT.getStatus());
        forumArticleService.updateForumArticleByArticleId(updateInfo, articleId);
        //添加积分
        Integer integral = SysCacheUtils.getSysSetting().getPostSetting().getPostIntegral();
        if (integral > 0 && ArticleStatusEnum.AUDIT.getStatus().equals(article.getStatus())) {
            userInfoService.updateUserIntergral(article.getUserId(), UserIntegralOperTypeEnum.POST_ARTICLE, UserIntegralChangeTypeEnum.ADD.getChangeType(), integral);
        }
    }

}
